home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Tele / C / Comet2.1.3 Folder / Comet / ft.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-23  |  21.9 KB  |  864 lines  |  [TEXT/dumv]

  1. /*
  2.  * COPYRIGHT 1987 CORNELL UNIVERSITY; All Rights Reserved
  3.  *  Please see detailed copyrights and disclaimers in "notice.h"
  4.  */
  5. #include <notice.h>
  6.  
  7. /* 8/14/87 kevin fixed Peter's new download code to work on the Mac */
  8.  
  9. /***************************************************************************
  10. ****                       3270 File Transfer                           ****
  11. ****          written by Peter Hoyt, Cornell Computer Services          ****
  12. ***************************************************************************/
  13.  
  14. #include <em.h>
  15.  
  16. #include <3270.h>
  17. #include <h19.h>
  18.  
  19.  
  20. unsigned char ft_table[] = {0x02,0x07,0x0d,0x11,0x13,0x7f,0xff};
  21. unsigned char ft_input_table[] = {0x02,0x11,0x13,0x7f,0xff};
  22.  
  23. /* This routine assembles incoming bytes from c19. */
  24.  
  25. #ifdef ANTIQUE
  26. /* ftc19 packet structure used for upload & download */
  27.  
  28. struct ftc19_pkt {
  29.     unsigned pkt_len;         /* total number of bytes to be uploaded */
  30.     unsigned len;             /* length of downloaded data */
  31.     unsigned chk;             /* chksum of downloaded */
  32.     char lbuff[4];            /* length characters xmitted */
  33.     char cbuff[4];            /* chksum characters xmitted */
  34.     char data[600];           /* xfer data buffer */
  35. } ftpkt, uppkt;
  36.  
  37. #endif
  38.  
  39. /* PAGE */
  40.  
  41. cft(data)                        /* handles version number */
  42. char data;
  43. {
  44.     emdp->cft_count = emdp->input_cnt = emdp->input_state = 0;
  45.     emdp->event_reg |= TFTP_ON;
  46.     (*emdp->putchar)((char) 0xfd);
  47.     (*emdp->putchar)((char) ftinit ((int) data, emdp->ibm_mode ? FALSE : TRUE));
  48.     (*emdp->putchar)((char) 0x0d);
  49.     mode = vtmode = CFT2MODE;
  50. }
  51.  
  52. cft2() 
  53. {                          
  54.     /* eat the next 70 characters */
  55.     if (++emdp->cft_count == 70)
  56.         mode = vtmode = C19FTMODE;
  57. }
  58.     
  59. /* This routine deals with incomming file transfer data:
  60.  *   The incomming bytes are assembled into an ftc19 packet.
  61.  *   It is checked for length, then gets escape sequences resolved,
  62.  *   and then gets its chksum verified. Finally its 7 bit data is expanded
  63.  *   into 8 bits and the file transfer routine ft3270() is called.
  64.  */
  65.     
  66. c19ft(data)
  67. char data;
  68. {
  69.     int i;
  70.     switch (emdp->input_state) {
  71.         case 0:                                 /* assembling the length of packet */
  72.             emdp->rcv_pkt.lbuff[emdp->input_cnt] = data;
  73.             if (emdp->input_cnt == 3) {
  74.                 for (emdp->rcv_pkt.len = 0, i = 0; i < 4; ++i)
  75.                     emdp->rcv_pkt.len = (emdp->rcv_pkt.len << 4) + (emdp->rcv_pkt.lbuff[i] & 0x0f);
  76.                 emdp->input_state = 1;
  77.             }
  78.             emdp->input_cnt = ++emdp->input_cnt & 3;    /* resets to 0 on way out */
  79.             break;
  80.         case 1:                                 /* assembling the chksum */
  81.             emdp->rcv_pkt.cbuff[emdp->input_cnt] = data;
  82.             if (emdp->input_cnt == 3) {
  83.                 for (emdp->rcv_pkt.chk = 0, i = 0; i < 4; ++i)
  84.                     emdp->rcv_pkt.chk = (emdp->rcv_pkt.chk << 4) + (emdp->rcv_pkt.cbuff[i] & 0x0f);
  85.                 emdp->input_state = 2;
  86.             }
  87.             emdp->input_cnt = ++emdp->input_cnt & 3;
  88.             break;
  89.         case 2:                                 /* gathering data */
  90.             if (data != 0x7f)
  91.                 *(emdp->rcv_pkt.data+emdp->input_cnt++) = data;
  92.             else {
  93.                 if (ft_process())            /* unravel headers & call ft3270() */
  94.                     ft_req();                  /* rc != 0: request re-xmission */
  95.                 emdp->input_cnt = emdp->input_state = 0;
  96.             }
  97.             break;
  98.     }
  99. }
  100.  
  101.  
  102. /* This routine processes an incoming block from telnet. */
  103.  
  104. tnft(ptr, len)
  105. char *ptr;
  106. int len;
  107. {
  108.     int i;
  109.  
  110.     if (len == 0)
  111.         return;
  112.         
  113.     for (;;) {                                              /* only a coding structure */
  114.         len -= 2;                                         /* skip 3270 cmd & WCC */
  115.         ptr += 2;
  116.         if (len < 6) break;                                /* 7171 sba's */
  117.         if (*ptr != 0x11 || *(ptr+3) != 0x11) {
  118.             cmd (ptr - 2, len + 2);                        /* see what host had to say */
  119.             break;
  120.             }
  121.         len -= 6;                                        /* skip 7171 headers */
  122.         ptr += 6;
  123.         if (len < 10) break;                            /* ft3270 stuff */
  124.  
  125.         for (emdp->rcv_pkt.len = 0, i = 0; i < 4; ++i)         
  126.             /* get packet length */
  127.             emdp->rcv_pkt.len = (emdp->rcv_pkt.len << 4) + (*ptr++ & 0x0f);
  128.         for (emdp->rcv_pkt.chk = 0, i = 0; i < 4; ++i)          
  129.             /* get packet chksum */
  130.             emdp->rcv_pkt.chk = (emdp->rcv_pkt.chk << 4) + (*ptr++ & 0x0f);
  131.  
  132.         emdp->input_cnt = len - 9;        
  133.             /* len(4) + chksum(4) + 0x7f trailer */
  134.         BlockMove(ptr, emdp->rcv_pkt.data, (long) emdp->input_cnt);
  135.         if (ft_process())                      /* unravel headers & call ft3270() */
  136.             ft_req();                         /* rc != 0: request re-xmission */
  137.         return;                                 /* do not cancel file transfer */
  138.     }
  139.     ft_done();                                              /* an error occurred */
  140. }
  141.  
  142.  
  143.  
  144. /* process an ft3270 packet */
  145. /* if ok call ft3270 & return 0 otherwise rc != 0 */
  146.  
  147. ft_process() 
  148. {
  149.     int i, length;
  150.     unsigned chksum;
  151.     unsigned char *buff, *buf1;
  152.  
  153.     if ((emdp->ft_flag & NEGO) && (!(emdp->ft_flag & C19) || (emdp->ft_flag & FTASCII)))
  154.         emdp->ft_flag |= NOSTRIP;
  155.     if (!(emdp->ft_flag & NEGO) || (emdp->ft_flag & FILERCV)) buff = emdp->ft3270_buff;
  156.         else                    buff = &emdp->ack_buff[0];
  157.     if (emdp->ft_flag & NOSTRIP) buf1 = buff;
  158.         else                     buf1 = emdp->tbuff;
  159.  
  160.     if (emdp->rcv_pkt.len != emdp->input_cnt)
  161.         return (1);
  162.     *(emdp->rcv_pkt.data+emdp->input_cnt) = 0;         /* pad with a zero for cksumming */
  163.     chksum = ~cksum (emdp->rcv_pkt.data, (emdp->input_cnt + 1) >> 1);
  164.     if (emdp->rcv_pkt.chk != (chksum)) 
  165.         return (2);
  166.     for (i = length = 0; i < emdp->input_cnt; i++, length++) {
  167.         if (*(emdp->rcv_pkt.data+i) == ESC_CHAR)
  168.             if (*(emdp->rcv_pkt.data+(++i)) != ESC_CHAR)
  169.                 *(emdp->rcv_pkt.data+i) = ft_input_table[*(emdp->rcv_pkt.data+i) & 0x0f];
  170.         buf1[length] = *(emdp->rcv_pkt.data+i);
  171.     }
  172.     /* now we have 7 bit data */
  173.  
  174.     if (!(emdp->ft_flag & NOSTRIP))
  175.         if ((length = bit_rest (emdp->tbuff, buff, length)) == 0) 
  176.             return (3);
  177.     ft3270(buff, length - 2);
  178.     return (0);
  179. }
  180.  
  181. /* build an ft3270 packet out of some file transfer data */
  182.  
  183. ft_upload(ptr, len)
  184. unsigned char *ptr;
  185. int len;
  186.     {
  187.     int i, j, k;
  188.     unsigned chksum;
  189.     unsigned char *buff;
  190.  
  191.     if (!(emdp->ft_flag & NOSTRIP)) {
  192.         buff = emdp->tbuff;                                    /* decide whether or not to */
  193.         len = bit_strip (ptr, emdp->tbuff, len);        /* make 7 bit data */
  194.     }
  195.     else                                                    /* avoid temp. buffer */
  196.         buff = ptr;
  197.  
  198.     for (i = j = 0; i < len; i++, j++) {         /* process special characters */
  199.         if (buff[i] == ESC_CHAR)                     /* into escape sequences */
  200.             *(emdp->send_pkt.data+j++) = ESC_CHAR;      /* esc duplicates itself */
  201.         else if ((k = ft_scan (ft_table, buff[i], NUMESC)) != -1) {
  202.             *(emdp->send_pkt.data+j++) = ESC_CHAR;      /* a hit */
  203.             buff[i] = 0x40 + k;                        /* use table index */
  204.         }
  205.         *(emdp->send_pkt.data+j) = buff[i];
  206.     }
  207.  
  208.     *(emdp->send_pkt.data+j) = 0;         /* pad with a zero for cksumming */
  209.     chksum = (~cksum (emdp->send_pkt.data, (j + 1) >> 1));
  210.     for (i = 12, k = 0; i >= 0; i -= 4, k++)  /* make length as 4 characters */
  211.         emdp->send_pkt.lbuff[k] = ((j >> i) & 0x0f) | 0x40;
  212.     for (i = 12, k = 0; i >= 0; i -= 4, k++)  /* make chksum as 4 characters */
  213.         emdp->send_pkt.cbuff[k] = ((chksum >> i) & 0x0f) | 0x40;
  214.     emdp->send_pkt.pkt_len = j + 8;                      /* store real length of packet */
  215.     ft_header();
  216.     send_block(emdp->send_pkt.lbuff, 8);
  217.     send_block(emdp->send_pkt.data, j);
  218.     ft_trailer();
  219. }
  220.  
  221. /*
  222.  *    Order of processing ft3270 data packets:
  223.  *      1) see if we are being shut down by host program.
  224.  *      2) quit abnormally if we are expecting host close & didn't get it.
  225.  *      3) check for user halt.
  226.  *      4) verify 1st byte of data stream.
  227.  *      5) if we haven't already processed negotiation, then this is it.
  228.  *      6) check for re-transmission request.
  229.  *      7) deal with respective eof's.
  230.  *      8) copy data.
  231.  */
  232.  
  233. ft3270(ptr, length)
  234. unsigned char *ptr;
  235. int length;
  236. {
  237.     unsigned char ack;
  238.     int i;
  239.  
  240.     if (*ptr == SHUTDOWN) {          /* normal termination */
  241.         ftack(RENTER);
  242.         ft_done();
  243.         return;
  244.     }
  245.     if (emdp->ft_flag & DONE) {             /* abnormal termination */
  246.         ftack(RPF10);
  247.         ft_done();
  248.         return;
  249.     }
  250.     if (emdp->ft_flag & HALT) {             /* user requested halt */
  251.         ftack(RPA1);
  252.         return;
  253.     }
  254.     if (*ptr++ != FT3270) {          /* verify 1st byte */
  255.         ftack(RPF9);
  256.         return;
  257.     }
  258.     if (!(emdp->ft_flag & NEGO)) {         /* we need to process negotiation string */
  259.         if (i = ftnego (ptr))         /* must be an error */
  260.             ftack (i);
  261. #ifdef PC
  262.         ft_banner();
  263. #else
  264.         arcinit(emdp->ftname);
  265.         byte_out (emdp->fttotal, 13);
  266. #endif
  267.         if (i == 0) emdp->ft_flag |= NEGO;
  268.         return;
  269.     }
  270.     if (*ptr == REXMIT) {             /* re-transmit is called for */
  271.         if (emdp->ft_flag & FILERCV)        /* if download */
  272.             ftack (emdp->ack_buff[0]);      /*     resend the last ack */
  273.         else                                /* else resend the buffer */
  274.             ft_upload (emdp->ft3270_buff, emdp->upload_cnt);
  275.         byte_out (++emdp->re_xmit, 15);
  276.         return;
  277.     }
  278.     if (emdp->ft_flag & FILERCV) {         /* check for eof from host */
  279.         if (*ptr == DOWNEOF)
  280.             emdp->ft_flag |= FEOF;
  281.     }
  282.     else if (emdp->ft_flag & FEOF) {      /* or see whether to send one */
  283.         ftack(RPA2);
  284.         fclose(emdp->ft1);
  285.         return;
  286.     }
  287.  
  288.     if (emdp->ft_flag & FILERCV) {         /* download */
  289.         ptr++;                             /* position at start of data */
  290.         emdp->ftxfered += length;
  291.         if (emdp->ft_flag & FTASCII) {
  292.             while (length--) {
  293.                 if (*ptr == 0x0a) {        /* end of "record" */
  294.                     /* if (ft_wrt(0xa)) return(); not on the mac--kevin*/
  295.                     if (ft_wrt(0x0d)) return();
  296.                 }
  297.                 else                            /* normal text */
  298.                     if (ft_wrt(*ptr)) return();
  299.                 ptr++;
  300.             }                         /* end while loop */
  301.         }
  302.         else
  303.             while (length--)
  304.                 if (ft_wrt(*ptr++)) return();
  305.  
  306.         ack = RENTER;                /* default ack */
  307.         if (emdp->ft_flag & FEOF) {
  308.             if (emdp->ftcnt > 0) {         /* write out any remaining data */
  309.                 if (fwrite (emdp->ftbuff, 1, emdp->ftcnt, emdp->ft1) != emdp->ftcnt)
  310.                     ack = RPF6;      /* error */
  311.             }
  312.             fclose(emdp->ft1);
  313.             if (ack == RENTER) {
  314.                 /* success: load the file into the edit window? */
  315.                 textdownedit(emdp->ftname);
  316.             }
  317.             emdp->ft_flag |= DONE;
  318.         }
  319.         ftack (ack);                /* ack with RENTER or RC */
  320.     }
  321.     else {                            /* upload */
  322.         emdp->ft3270_buff[0] = RENTER;
  323.         for (emdp->upload_cnt = 1; emdp->upload_cnt <= emdp->ftlen; emdp->ftptr++, emdp->ftcnt--) {
  324.             if (emdp->ftcnt == 0) {
  325.                 if ((emdp->ftcnt = fread (emdp->ftptr = emdp->ftbuff, 1, DOSLEN, emdp->ft1)) == 0) {
  326.                     emdp->ft_flag |= FEOF;
  327.                     break;
  328.                 }
  329.             }
  330.             if (emdp->ft_flag & FTASCII) {
  331.                 /* if (*emdp->ftptr == 0x1a || *emdp->ftptr == 0x0d);     ignore CR & EOF NOT ON THE MAC--kevin*/
  332.                 if (*emdp->ftptr == 0x0d)
  333.                     emdp->ft3270_buff[emdp->upload_cnt++] = 0x0a;        /* CR -> LF for upload on the Mac */
  334.                 else
  335.                     emdp->ft3270_buff[emdp->upload_cnt++] = *emdp->ftptr;
  336.                 /* TODO CR-LF??? */
  337.             }
  338.             else
  339.                 emdp->ft3270_buff[emdp->upload_cnt++] = *emdp->ftptr;
  340.         }                             /* ....end of for loop */
  341.         emdp->ftxfered += (emdp->upload_cnt - 1);
  342.         ft_upload(emdp->ft3270_buff, emdp->upload_cnt);
  343.     }
  344.     byte_out (emdp->ftxfered, 14);
  345. }                                                 /* end of ft3170 subroutine */
  346.  
  347.  
  348. /* return index of passed character or -1 if not present */
  349.  
  350. ft_scan(charp, thechar, len)
  351. register char * charp;
  352. register char thechar;
  353. register int len;
  354. {
  355.     int thelen;
  356.  
  357.     thelen = len;
  358.     for ( ; len > 0 && *charp++ != thechar ; --len) 
  359.         ;
  360.     if (len)
  361.         return(thelen - len);
  362.     else
  363.         return(-1);
  364. }
  365.  
  366.  
  367.  
  368. /* repeatedly restore the high order bits from 8th byte to 7 previous bytes */
  369.  
  370. bit_rest(from, to, len)
  371. register char * from;
  372. register char * to;
  373. int len;
  374. {
  375.     register unsigned char highbits;
  376.     register int count;
  377.     register int newlen;
  378.  
  379.     newlen = 0;
  380.     for ( ; len > 0; len -= 8, from++) {
  381.         if (len < 8)
  382.             count = len - 1;
  383.         else
  384.             count = 7;
  385.         highbits = *(from + count);
  386.         newlen += count;
  387.         while (--count >= 0) {
  388.             /* Note that the bits for final sequences < 8 wind up in different places */
  389.             if (highbits & 0x01)
  390.                 *to++ = *from++ | 0x80;
  391.             else
  392.                 *to++ = *from++;
  393.             highbits >>= 1;
  394.         }
  395.     }
  396.     return(newlen);
  397. }
  398.  
  399. /* repeatedly take the high order bits from 7 consecutive bytes & store them in 8th byte */
  400.  
  401.  
  402. bit_strip(from, to, len)
  403. register char * from;
  404. register char * to;
  405. int len;
  406. {
  407.     register unsigned char * highbits;
  408.     register int count;
  409.     register int newlen;
  410.     register char frombyte;
  411.  
  412.     newlen = 0;
  413.     for ( ; len > 0; len -= 7, to++) {
  414.         /* outside loop:  get the high bit marker for 1-7 bytes repeatedly */
  415.         if (len < 7)
  416.             count = len;
  417.         else
  418.             count = 7;
  419.         highbits = to + count;
  420.         *highbits = 0;
  421.         newlen += count + 1;
  422.         while (--count >= 0) {
  423.             frombyte = *from++;
  424.             if (frombyte & 0x80) {
  425.                 frombyte &= 0x7f;
  426.                 *highbits |= 0x80;
  427.             }
  428.             *to++ = frombyte;
  429.             *highbits >>= 1;
  430.         }
  431.         if (len < 7)
  432.             *highbits >>= 7 - len;
  433.     }
  434.     return(newlen);
  435. }
  436.  
  437.  
  438. /***************************************************************************
  439. ****          3270 File Transfer Negotiation & Utility Routines         ****
  440. ****          written by Peter Hoyt, Cornell Computer Services          ****
  441. ***************************************************************************/
  442.  
  443.  
  444. /* initialize routine for file transfer:
  445.  *    ptr points to a 32 bit unsigned (high bytes first) length in bytes
  446.  *    beyond that is a one byte extra field
  447.  *      bit 0: replace filename if it already exists
  448.  *      bit 1: ascii/ebcdic conversion
  449.  *      bit 2: use default binary filename extensions
  450.  *    beyond that is the path spec terminated by a binary zero
  451.  */
  452.  
  453. ftnego(ptr)
  454. unsigned char *ptr;
  455.    {
  456.    unsigned char direction, *ftype;
  457.    unsigned long length, avail;
  458.    int i, j;
  459.    union {
  460.       unsigned long _l;
  461.       unsigned char _c[4];
  462.       } foo;
  463.     char * ftnamep;
  464.  
  465.    direction = *ptr++;
  466.    for (length = 0, i = 0; i < 4; i++)
  467.       length = (length << 8) + (*ptr++);
  468.    emdp->extra  = *ptr;
  469.    ftnamep = ++ptr;               /* ptr now points to path spec */
  470.  
  471.    /* convert filespec to ascii and isolate filename extension */
  472.    for (ftype = 0, emdp->fnamelen = 0; *ptr; emdp->fnamelen++, ptr++)
  473.       if ((*ptr = *(ebctoasc + *ptr)) == '.') ftype = ptr + 1;
  474.  
  475. #ifndef PC
  476.     /* reinterpret the pathname for the macintosh */
  477.     
  478.     emdp->ftname = malloc((unsigned) strlen(ftnamep) + 1);
  479.     macpath(ftnamep, emdp->ftname);
  480.     mac_setdownvol();    /* fix the directory for multiple sessions */
  481.   
  482. #endif
  483.  
  484.  
  485.    emdp->ack_buff[0] = RENTER;           /* if all goes well ack with RENTER */
  486.  
  487.    emdp->ft_flag |= (emdp->extra & CONV);    /* CONV bit turns on FTASCII flag */
  488.    if (emdp->extra & LOOKUP) {         /* let pc determine defaults */
  489.       emdp->ft_flag &= ~FTASCII;         /* clear conversion bit */
  490.       
  491.       /* only the PC version has this code... */
  492.          emdp->ft_flag |= FTASCII;                    /* no table match: do conversion */
  493.       emdp->ack_buff[1] = emdp->ft_flag & FTASCII;       /* return non zero if no match */
  494.    }
  495.    
  496.    if (direction == DOWNLOAD) {
  497.       emdp->ft_flag |= FILERCV;
  498.       emdp->fttotal = length;
  499.       if (emdp->extra & REP)                      /* replace file of same name */
  500.          unlink(emdp->ftname);
  501.       else if ( (emdp->ft1 = fopen (emdp->ftname, "r")) != NULL) { 
  502.                 /* file already exists */
  503.             fclose(emdp->ft1);
  504.             return(RPF1);
  505.       }
  506.       if ((avail = free_sp (emdp->ftname)) == 0)  /* see if room on disk */
  507.          return (RPF2);
  508.       if (avail < length)                   /* insufficient space */
  509.          return (RPF3);
  510.       if ((emdp->ft1 = fopen (emdp->ftname, "w")) == 0) /* open for real now */
  511.          return (RPF4);
  512.       ft_upload (&emdp->ack_buff[0], 2);
  513.       return (0);                           /* successful negotiations */
  514.    }
  515.    else if (direction == UPLOAD) {
  516.         textupedit(emdp->ftname);        /* convert text if necessary */
  517.  
  518.       length = 0;
  519.       if ((emdp->ft1 = fopen (emdp->ftname, "r")) == 0)     /* open failure */
  520.          return (RPF5);
  521.       if (fseek (emdp->ft1, length, 2) == -1)         /* position at eof */
  522.          return (RPF7);
  523.       emdp->fttotal = foo._l = ftell (emdp->ft1);           /* get length in bytes */
  524.       if (fseek (emdp->ft1, length, 0) == -1)         /* reposition at tof */
  525.          return (RPF8);
  526.  
  527.       for (i = 3; i >= 0; i--)                  /* copy length to buffer */
  528.          emdp->ack_buff[i + 2] = foo._c[i];                    /* PORT changed for mac, was emdp->ack_buff[5-i], kevin */
  529.       ft_upload (&emdp->ack_buff[0], 6);
  530.       emdp->send_pkt.data = emdp->xfer1_buff;               /* switch the buffers */
  531.       emdp->rcv_pkt.data  = emdp->xfer2_buff;
  532.       return (0);                               /* successful negotiations */
  533.    }
  534.    else                                         /* error! */
  535.       return (RPF9);
  536. }
  537.  
  538.  
  539. /* initial contact with host program */
  540.  
  541. ftinit(hostvers, c19)
  542. int hostvers, c19;
  543. {
  544.    if (c19) emdp->ftlen = C19FTLEN;
  545.       else  emdp->ftlen = TNFTLEN;
  546.  
  547.  
  548.     if (makeftmem())
  549.         return(ESC_CHAR);                        /* tell host to continue */
  550.  
  551.    emdp->rcv_pkt.data  = emdp->xfer1_buff;        /* buffers default */
  552.    emdp->send_pkt.data = emdp->xfer2_buff;
  553.  
  554.    switch (hostvers) {
  555.       case 20:                             /* acceptable version numbers */
  556.          emdp->ftcnt     = 0;           /* index into DOS file buffer */
  557.          emdp->ftxfered  = emdp->re_xmit     = 0;
  558.          emdp->input_cnt = emdp->input_state = 0;
  559.          emdp->ft_flag   = 0;
  560.          if (c19) emdp->ft_flag |= C19;
  561.          return (PROGVERS);             /* tell host to continue */
  562.          break;
  563.       default:                /* tell host no dice */
  564.          return (ESC_CHAR);
  565.       }
  566.    }
  567.  
  568. /* send a packet of one byte acknowledgement */
  569.  
  570. ftack(x)
  571. unsigned x;
  572.     {
  573.    emdp->ack_buff[0] = x;
  574.    ft_upload (&emdp->ack_buff[0], 1);
  575.    if (x != RENTER && x != REXMIT)
  576.       emdp->ft_flag |= DONE;
  577.    }
  578.  
  579.  
  580.  
  581. /* the following are Mac-specific routines */
  582.  
  583. /* draw a circle for a pie to show how much of a file has been transferred */
  584.  
  585.  
  586. arcinit(filename)
  587. unsigned char * filename;
  588. {
  589.     GrafPtr oldport;
  590.     int oldfont;
  591.     int oldsize;
  592.     Str255 filesize;
  593.  
  594.     GetPort(&oldport);
  595.  
  596.     emdp->arcdeg = 0;
  597.     emdp->arcrect.top = 60;
  598.     emdp->arcrect.left = 140;
  599.     emdp->arcrect.bottom = 270;
  600.     emdp->arcrect.right = 350;
  601.  
  602.     emdp->textrect.top = 20;
  603.     emdp->textrect.left = 20;
  604.     emdp->textrect.bottom = 80;
  605.     emdp->textrect.right = 370;
  606.     
  607. #ifdef FTWIND
  608.     ctop(filename);
  609.     arcwind = NewWindow((Ptr) NULL, &emdp->arcrect, filename, (Boolean) TRUE, 0, (WindowPtr) -1, (Boolean) FALSE, 0L);
  610.     ptoc(filename);
  611.     SetPort(arcwind);
  612.  
  613.     emdp->arcrect.top -= 10;
  614.     emdp->arcrect.left -= 10;
  615.     emdp->arcrect.bottom -= 10;
  616.     emdp->arcrect.right -= 10;
  617. #else
  618.     SetPort(emwindow);
  619. #endif
  620.  
  621.     selreset(emdp);                        /* reset selection rectangle */
  622.  
  623.     /* draw the file name */
  624.     oldfont = thePort->txFont;
  625.     oldsize = thePort->txSize;
  626.     TextFont(0);    /* System Font */
  627.     TextSize(12);
  628.  
  629.     ClipRect(&emdp->textrect);
  630.     MoveTo(emdp->textrect.left + 10, emdp->textrect.top + 20);
  631.     DrawText(filename, 0, strlen(filename));
  632.  
  633.     MoveTo(emdp->textrect.left + 10, emdp->textrect.top + 35);
  634.     NumToString(emdp->fttotal, &filesize);
  635.     DrawString(&filesize);
  636.     DrawString("\P bytes");
  637.  
  638.     MoveTo(emdp->textrect.left + 10, emdp->textrect.top + 50);
  639.     DrawString("\PUse PA1 to abort");
  640.  
  641.     ClipRect(&emwindow->portRect);
  642.     TextFont(oldfont);
  643.     TextSize(oldsize);
  644.  
  645.     FrameOval(&emdp->arcrect);
  646.  
  647.     SetPort(oldport);
  648. }
  649.  
  650.  
  651. /* erase the circle */
  652.  
  653. arcerase()
  654. {
  655. #ifdef FTWIND
  656.     DisposeWindow(arcwind);
  657. #else
  658.     EraseRect(&emdp->arcrect);
  659.     EraseRect(&emdp->textrect);
  660. #endif
  661. }
  662.  
  663.  
  664. byte_out(cnt, line)
  665. long cnt;
  666. int  line;
  667. {
  668.     int newarc;
  669.     float total;
  670.     float count;
  671.  
  672.     if (line == 13)
  673.         /* Peter's total count, ignore it */
  674.         return(-1);
  675.     if (cnt > emdp->fttotal)
  676.         count = emdp->fttotal;
  677.     else
  678.         count = cnt;
  679.     total = emdp->fttotal;
  680.     newarc = (count / emdp->fttotal) * 360;
  681.         /* percentage of arc completed */
  682.     if (newarc > emdp->arcdeg) {
  683.         GrafPtr oldport;
  684.  
  685.         GetPort(&oldport);
  686. #ifdef FTWIND
  687.         SetPort(arcwind);
  688. #else
  689.         SetPort(emwindow);
  690. #endif
  691.         /* draw more of the wedge */
  692. #ifdef INVERT
  693.         InvertArc(&emdp->arcrect, emdp->arcdeg, newarc - emdp->arcdeg);
  694. #else
  695.         FillArc(&emdp->arcrect, emdp->arcdeg, newarc - emdp->arcdeg, &gray);
  696. #endif        emdp->arcdeg = newarc;
  697.         SetPort(oldport);
  698.     }
  699. }
  700.  
  701. arcrefresh()
  702. {
  703.     if (! (emdp->event_reg & TFTP_ON))
  704.         return(-1);
  705.     EraseRect(&emdp->arcrect);
  706.     arcinit(emdp->ftname);
  707.  
  708.     byte_out(emdp->ftxfered, 14);
  709. }
  710.  
  711. /* restore Macintosh program to terminal emulation state */
  712.  
  713. ft_done() 
  714. {        
  715.     extern int mode;
  716.  
  717.     emdp->event_reg |= LINE_25;
  718.     emdp->event_reg &= ~TFTP_ON;
  719.     msetsendm(TRUE);
  720.     mode = vtmode = 0;
  721.     free(emdp->ftname);
  722.     arcerase();
  723. }
  724.  
  725. /* user requested break via PA1 */
  726.  
  727. ft_usr() {
  728.    if (!(emdp->ft_flag & HALT))         emdp->ft_flag |= HALT;
  729.       else if (!(emdp->ft_flag & DONE)) emdp->ft_flag |= DONE;
  730.       else ft_done();
  731.    }
  732.  
  733. /* request a re-xmission */
  734.  
  735. ft_req() {
  736.    ftack (RPA3);
  737.    byte_out (++emdp->re_xmit, 15);
  738.    }
  739.  
  740.  
  741. /* place character in DOS buffer and write when full */
  742.  
  743. ft_wrt (c)
  744. char c;
  745.    {
  746.    emdp->ftbuff[emdp->ftcnt++] = c;
  747.    if (emdp->ftcnt != DOSLEN) return(0);
  748.    if (fwrite (emdp->ftbuff, 1, emdp->ftcnt, emdp->ft1) != emdp->ftcnt) {
  749.       ftack(RPF6);
  750.       return(1);
  751.       }
  752.    emdp->ftcnt = 0;
  753.    return(0);
  754.    }
  755.  
  756.  
  757. /* free memory used by transfer buffers */
  758.  
  759. ftrecovermem(twp)
  760. struct winds * twp;
  761. {
  762.     if (twp->xfer1_buff)
  763.         free(twp->xfer1_buff);
  764.     if (twp->xfer2_buff)
  765.         free(twp->xfer2_buff);
  766.     if (twp->tbuff)
  767.         free(twp->tbuff);
  768.     if (twp->ft3270_buff)
  769.         free(twp->ft3270_buff);
  770.     if (twp->ftbuff)
  771.         free(twp->ftbuff);
  772.  
  773.     twp->xfer1_buff = NULL;
  774.     twp->xfer2_buff = NULL;
  775.     twp->tbuff = NULL;
  776.     twp->ft3270_buff = NULL;
  777.     twp->ftbuff = NULL;
  778. }
  779.  
  780.  
  781. /* allocate memory for a file transfer, return -1 if we can't */
  782.  
  783. makeftmem()
  784. {
  785.     if (emdp->xfer1_buff)
  786.         return(0);
  787.         
  788.     if (memtest((long) (MAXLEN + TBUFLEN + TNFTLEN + DOSLEN + TNFTLEN), "to perform download")) {
  789.         /* verify there's enough memory */
  790.         emdp->xfer1_buff = malloc(MAXLEN);
  791.             emdp->rcv_pkt.data  = emdp->xfer1_buff;     /* buffers default */
  792.         emdp->xfer2_buff = malloc(20);
  793.             emdp->send_pkt.data = emdp->xfer2_buff;
  794.         emdp->tbuff = malloc(TBUFLEN);
  795.         emdp->ft3270_buff = malloc(TNFTLEN+10);
  796.         emdp->ftbuff = malloc(DOSLEN);
  797.     }
  798.     if (   emdp->xfer1_buff == NULL
  799.         || emdp->xfer2_buff == NULL
  800.         || emdp->tbuff         == NULL
  801.         || emdp->ft3270_buff == NULL
  802.         || emdp->ftbuff     == NULL
  803.     ) {
  804.         ftrecovermem(emdp);
  805.         return(-1);
  806.     }
  807.     return(0);
  808. }
  809.  
  810.  
  811. /* ft3270 support */
  812.  
  813.  
  814. /* header for file transfer packets */
  815.  
  816. ft_header() 
  817. {
  818.     if (emdp->ft_flag & C19) {
  819.         /* no header */
  820.         ;
  821.     }
  822.     else {
  823.         /* 3270 currently always uses Telnet anyway... */
  824.         
  825.         (*emdp->putchar)(0xe8);
  826.         (*emdp->putchar)(0x00);
  827.         (*emdp->putchar)(0x00);
  828.     }
  829. }
  830.  
  831. /* trailer for file transfer packets */
  832.  
  833. ft_trailer() 
  834. {
  835.     if (emdp->ft_flag & C19) {
  836.         (*emdp->putchar)(CR);
  837.         (*emdp->putflush)();
  838.     }
  839.     else {
  840.         (*emdp->putchar)(0x0d);
  841.         (*emdp->putchar)(TNIAC);
  842.         (*emdp->putchar)(0xef);
  843.         (*emdp->putflush)();
  844.     }
  845. }
  846.  
  847. /* send a block of data */
  848.             
  849. send_block(ptr, len)
  850. unsigned char *ptr;
  851. int len;
  852. {
  853.     if (emdp->conntype == CONN_SERD) {
  854.         /* try to fix hanging problems with Sytek */
  855.         sersendcount(ptr, len);
  856.     }
  857.     else {
  858.         len++;
  859.         while (--len)
  860.             (*emdp->putchar)(*ptr++);
  861.     }
  862. }
  863.  
  864.